unit MVC.DataSet;

{$mode ObjFPC}{$H+}

interface

uses
  Classes, SysUtils, mvc.Config, MVC.Tool, MVC.LogUnit, SQLDB, DB;

type
  IDataSet = interface
    function DS: TSQLQuery;
    function toJSONArray: string;
    function toJSONObject: string;
  end;

  { TDataSet }

  TDataSet = class(TInterfacedObject, IDataSet)
  private
    dataset: TSQLQuery;
    function checkType(dbtype: TFieldType): boolean;
  public
    function DS: TSQLQuery;
    function toJSONArray: string;
    function toJSONObject: string;
    constructor Create();
    destructor Destroy; override;
  end;

function IIDataSet: IDataSet;

implementation

{ TDataSet }
function IIDataSet: IDataSet;
var
  ds: IDataSet;
begin
  ds := TDataSet.Create;
  Result := ds;
end;

function TDataSet.DS: TSQLQuery;
begin
  Result := dataset;
end;

function TDataSet.checkType(dbtype: TFieldType): boolean;
begin
  if dbtype in [ftString, ftWideString, ftUnknown, ftWideMemo, ftMemo,
    ftDate, ftDateTime, ftTime, ftFmtMemo, ftTimeStamp, ftFixedChar,
    ftFixedWideChar] then
  begin
    Result := True;
  end
  else
  begin
    Result := False;
  end;
end;

function TDataSet.toJSONArray: string;
var
  i: integer;
  ret: string;
  ftype: TFieldType;
  json, item, key, Value: string;
begin
  ret := '';
  try
    if dataset = nil then
    begin
      Result := '[]';
      exit;
    end;
    json := '';
    with dataset do
    begin
      First;

      while not EOF do
      begin
        item := '{';
        for i := 0 to Fields.Count - 1 do
        begin
          ftype := Fields[i].DataType;
          if Config.JsonToLower then
            key := Fields[i].DisplayLabel.ToLower
          else
            key := Fields[i].DisplayLabel;
          if checkType(ftype) then
            Value := '"' + IITool.UnicodeEncode(Fields[i].AsString) + '"'
          //Value := '"' + (Fields[i].AsString) + '"'
          else if ftype = ftBoolean then
            Value := Fields[i].AsString.ToLower
          else
            Value := Fields[i].AsString;

          if Value = '' then
            Value := '0';
          item := item + '"' + key + '"' + ':' + Value + ',';
        end;
        item := copy(item, 1, item.Length - 1);
        item := item + '},';
        json := json + item;
        Next;
      end;
    end;
    if json.Length > 1 then
      json := copy(json, 1, json.Length - 1);
    json := '[' + json + ']';
    Result := json;
  except
    on e: Exception do
    begin
      log(e.Message);
    end;
  end;
end;

function TDataSet.toJSONObject: string;
var
  i: integer;
  ftype: TFieldType;
  json, item, key, Value: string;
begin
  json := '';
  try
    if dataset = nil then
    begin
      Result := '{}';
      exit;
    end;
    with dataset do
    begin

      if not IsEmpty then
      begin
        item := '{';
        for i := 0 to Fields.Count - 1 do
        begin
          ftype := Fields[i].DataType;
          if Config.JsonToLower then
            key := Fields[i].DisplayLabel.ToLower
          else
            key := Fields[i].DisplayLabel;

          if checkType(ftype) then
            Value := '"' + IITool.UnicodeEncode(Fields[i].AsString) + '"'
          else if ftype = ftBoolean then
            Value := Fields[i].AsString.ToLower
          else
            Value := Fields[i].AsString;

          if Value = '' then
            Value := '0';
          item := item + '"' + key + '"' + ':' + Value + ',';
        end;
        item := copy(item, 1, item.Length - 1);
        item := item + '},';
        json := json + item;
        Next;
      end;
    end;
    if json.Length > 1 then
      json := copy(json, 1, json.Length - 1);
    Result := json;
  except
    on e: Exception do
    begin
      log(e.Message);
    end;
  end;
end;

constructor TDataSet.Create;
begin
  dataset := TSQLQuery.Create(nil);
end;

destructor TDataSet.Destroy;
begin
  dataset.Free;
  inherited Destroy;
end;

end.
